﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Automation;
using System.Collections;
using Tedds_Tool.Automatables;
using CommonInterfaces.Models;
using Compiled_Tests;
using Compiled_Tests.Utils;
using LEET.LEETCommon.WidgetLookup;

namespace Tedds_Tool
{
    public class ElementState : IElementState
    {

        private AutomationElement root;
        IDictionary<String, IDictionary<String, String>> cache;
        IList<ILEETHackModual> hacks;
        
        public ElementState(IBox box, IList<ILEETHackModual> hacks) : this(box.RootElement, hacks) { }
        
        public ElementState(AutomationElement ae, IList<ILEETHackModual> hacks)
        {
            this.hacks = hacks;
            this.root = ae;
            cache = new Dictionary<String, IDictionary<String, String>>();
            cacheElements();
        }

        public ElementState()
        {
            cache = new Dictionary<String, IDictionary<String, String>>();
        }

        public IEnumerable<string> Property(string elem)
        {
            IDictionary<String, String> props = null;
            cache.TryGetValue(elem, out props);
            if (props != null)
                return props.Keys;
            else
                return new List<String>();
        }

        public string ValueOf(string elem, string prop)
        {
            IDictionary<String, String> props = null;
            cache.TryGetValue(elem, out props);
            if (props != null)
            {
                String ret = null;
                props.TryGetValue(prop, out ret);
                if (ret != null)
                    return ret;
            }
            return "";
        }

        public IEnumerable<string> Elements { 
            get
            {
                return cache.Keys;
            }
        }

        private void cacheElements()
        {
            if (root == null) return;
            AutomationElementCollection aec;
            CacheRequest cr = new CacheRequest();

            cr.Add(AutomationElement.AutomationIdProperty);
            cr.Add(AutomationElement.NameProperty);
            cr.TreeScope = TreeScope.Subtree;               //current element + all descendants

            using (cr.Activate())
            {
                aec = root.FindAll(TreeScope.Subtree, new PropertyCondition(AutomationElement.IsOffscreenProperty, false));
            }

            foreach (AutomationElement ae in aec)
            {
                string name = ae.Cached.Name.Trim();
                string id = ae.Cached.AutomationId.Trim();

                string elem;
                if (!String.IsNullOrEmpty(id))
                    elem = id;
                else if(!String.IsNullOrEmpty(name))
                    elem = name;
                else
                    continue;
                
                //create elem entry
                IDictionary<String, String> properties = new Dictionary<String, String>();

                AutomationPattern[] pat = ae.GetSupportedPatterns();
                ArrayList patterns = ArrayList.Adapter(pat);

                //   \.Add\("{[a-zA-Z]+}{[a-zA-Z\.]+}"\)
                //   \.Add("\1\2", (patterns[index] as \1)\2\.ToString()\.Trim())
                int index;
                if ((index = patterns.IndexOf(WindowPattern.Pattern)) >= 0)
                {
                    WindowPattern pattern = ae.GetCurrentPattern(WindowPattern.Pattern) as WindowPattern;
                    properties.Add("WindowPattern.Current.CanMaximize", pattern.Current.CanMaximize.ToString().Trim());
                    properties.Add("WindowPattern.Current.CanMinimize", pattern.Current.CanMinimize.ToString().Trim());
                    properties.Add("WindowPattern.Current.IsModal", pattern.Current.IsModal.ToString().Trim());
                    properties.Add("WindowPattern.Current.IsTopmost", pattern.Current.IsTopmost.ToString().Trim());
                    properties.Add("WindowPattern.Current.WindowInteractionState", pattern.Current.WindowInteractionState.ToString().Trim());
                    properties.Add("WindowPattern.Current.WindowVisualState", pattern.Current.WindowVisualState.ToString().Trim());
                }
                if ((index = patterns.IndexOf(ValuePattern.Pattern)) >= 0)
                {
                    ValuePattern pattern = ae.GetCurrentPattern(ValuePattern.Pattern) as ValuePattern;
                    properties.Add("ValuePattern.Current.Value", pattern.Current.Value.ToString().Trim());
                    properties.Add("ValuePattern.Current.IsReadOnly", pattern.Current.IsReadOnly.ToString().Trim());
                }
                if ((index = patterns.IndexOf(TransformPattern.Pattern)) >= 0)
                {
                    TransformPattern pattern = ae.GetCurrentPattern(TransformPattern.Pattern) as TransformPattern;
                    properties.Add("TransformPattern.Current.CanMove", pattern.Current.CanMove.ToString().Trim());
                    properties.Add("TransformPattern.Current.CanResize", pattern.Current.CanResize.ToString().Trim());
                    properties.Add("TransformPattern.Current.CanRotate", pattern.Current.CanRotate.ToString().Trim());
                }
                if ((index = patterns.IndexOf(SelectionPattern.Pattern)) >= 0)
                {
                    SelectionPattern pattern = ae.GetCurrentPattern(SelectionPattern.Pattern) as SelectionPattern;
                    properties.Add("SelectionPattern.Current.SelectionProperty", pattern.Current.GetSelection().ToString().Trim());
                    properties.Add("SelectionPattern.Current.IsSelectionRequired", pattern.Current.IsSelectionRequired.ToString().Trim());
                    properties.Add("SelectionPattern.Current.CanSelectMultiple", pattern.Current.CanSelectMultiple.ToString().Trim());
                }
                if ((index = patterns.IndexOf(SelectionItemPattern.Pattern)) >= 0)
                {
                    SelectionItemPattern pattern = ae.GetCurrentPattern(SelectionItemPattern.Pattern) as SelectionItemPattern;
                    if (pattern.Current.SelectionContainer != null)
                        properties.Add("SelectionItemPattern.Current.SelectionContainer", pattern.Current.SelectionContainer.ToString().Trim());
                    properties.Add("SelectionItemPattern.Current.IsSelected", pattern.Current.IsSelected.ToString().Trim());
                }
                if ((index = patterns.IndexOf(ScrollPattern.Pattern)) >= 0)
                {
                    ScrollPattern pattern = ae.GetCurrentPattern(ScrollPattern.Pattern) as ScrollPattern;
                    properties.Add("ScrollPattern.Current.HorizontallyScrollable", pattern.Current.HorizontallyScrollable.ToString().Trim());
                    properties.Add("ScrollPattern.Current.HorizontalScrollPercent", pattern.Current.HorizontalScrollPercent.ToString().Trim());
                    properties.Add("ScrollPattern.Current.HorizontalViewSize", pattern.Current.HorizontalViewSize.ToString().Trim());
                    //properties.Add("ScrollPattern.Current.NoScroll", pattern.Current.NoScroll.ToString().Trim());
                    properties.Add("ScrollPattern.Current.VerticallyScrollable", pattern.Current.VerticallyScrollable.ToString().Trim());
                    properties.Add("ScrollPattern.Current.VerticalScrollPercent", pattern.Current.VerticalScrollPercent.ToString().Trim());
                    properties.Add("ScrollPattern.Current.VerticalViewSize", pattern.Current.VerticalViewSize.ToString().Trim());
                }
                //if ((index = patterns.IndexOf(ScrollPatternIdentifiers.Pattern)) >= 0)
                //{
                //    properties.Add("ScrollPatternIdentifiers.Current.HorizontallyScrollable", pattern.Current.HorizontallyScrollable.ToString().Trim());
                //    properties.Add("ScrollPatternIdentifiers.Current.HorizontalScrollPercent", pattern.Current.HorizontalScrollPercent.ToString().Trim());
                //    properties.Add("ScrollPatternIdentifiers.Current.HorizontalViewSize", pattern.Current.HorizontalViewSize.ToString().Trim());
                //    properties.Add("ScrollPatternIdentifiers.Current.NoScroll", pattern.Current.NoScroll.ToString().Trim());
                //    properties.Add("ScrollPatternIdentifiers.Current.VerticallyScrollable", pattern.Current.VerticallyScrollable.ToString().Trim());
                //    properties.Add("ScrollPatternIdentifiers.Current.VerticalScrollPercent", pattern.Current.VerticalScrollPercent.ToString().Trim());
                //    properties.Add("ScrollPatternIdentifiers.Current.VerticalViewSize", pattern.Current.VerticalViewSize.ToString().Trim());
                //}
                if ((index = patterns.IndexOf(RangeValuePattern.Pattern)) >= 0)
                {
                    RangeValuePattern pattern = ae.GetCurrentPattern(RangeValuePattern.Pattern) as RangeValuePattern;
                    properties.Add("RangeValuePattern.Current.IsReadOnly", pattern.Current.IsReadOnly.ToString().Trim());
                    properties.Add("RangeValuePattern.Current.LargeChange", pattern.Current.LargeChange.ToString().Trim());
                    properties.Add("RangeValuePattern.Current.Maximum", pattern.Current.Maximum.ToString().Trim());
                    properties.Add("RangeValuePattern.Current.Minimum", pattern.Current.Minimum.ToString().Trim());
                    properties.Add("RangeValuePattern.Current.SmallChange", pattern.Current.SmallChange.ToString().Trim());
                    properties.Add("RangeValuePattern.Current.Value", pattern.Current.Value.ToString().Trim());
                }
                if ((index = patterns.IndexOf(MultipleViewPattern.Pattern)) >= 0)
                {
                    MultipleViewPattern pattern = ae.GetCurrentPattern(MultipleViewPattern.Pattern) as MultipleViewPattern;
                    properties.Add("MultipleViewPattern.Current.CurrentView", pattern.Current.CurrentView.ToString().Trim());
                    properties.Add("MultipleViewPattern.Current.SupportedViews", pattern.Current.GetSupportedViews().ToString().Trim());
                }
                if ((index = patterns.IndexOf(GridPattern.Pattern)) >= 0)
                {
                    GridPattern pattern = ae.GetCurrentPattern(GridPattern.Pattern) as GridPattern;
                    properties.Add("GridPattern.Current.ColumnCount", pattern.Current.ColumnCount.ToString().Trim());
                    properties.Add("GridPattern.Current.RowCount", pattern.Current.RowCount.ToString().Trim());
                }
                if ((index = patterns.IndexOf(GridItemPattern.Pattern)) >= 0)
                {
                    GridItemPattern pattern = ae.GetCurrentPattern(GridItemPattern.Pattern) as GridItemPattern;
                    properties.Add("GridItemPattern.Current.Column", pattern.Current.Column.ToString().Trim());
                    properties.Add("GridItemPattern.Current.ColumnSpan", pattern.Current.ColumnSpan.ToString().Trim());
                    properties.Add("GridItemPattern.Current.ContainingGrid", pattern.Current.ContainingGrid.ToString().Trim());
                    properties.Add("GridItemPattern.Current.Row", pattern.Current.Row.ToString().Trim());
                    properties.Add("GridItemPattern.Current.RowSpan", pattern.Current.RowSpan.ToString().Trim());
                }
                if ((index = patterns.IndexOf(ExpandCollapsePattern.Pattern)) >= 0)
                {
                    ExpandCollapsePattern pattern = ae.GetCurrentPattern(ExpandCollapsePattern.Pattern) as ExpandCollapsePattern;
                    properties.Add("ExpandCollapsePattern.Current.ExpandCollapseState", pattern.Current.ExpandCollapseState.ToString().Trim());
                }
                if ((index = patterns.IndexOf(DockPattern.Pattern)) >= 0)
                {
                    DockPattern pattern = ae.GetCurrentPattern(DockPattern.Pattern) as DockPattern;
                    properties.Add("DockPattern.Current.DockPosition", pattern.Current.DockPosition.ToString().Trim());
                }
                if ((index = patterns.IndexOf(TablePattern.Pattern)) >= 0)
                {
                    TablePattern pattern = ae.GetCurrentPattern(TablePattern.Pattern) as TablePattern;
                    properties.Add("TablePattern.Current.ColumnHeaders", pattern.Current.GetColumnHeaders().ToString().Trim());
                    properties.Add("TablePattern.Current.RowHeaders", pattern.Current.GetRowHeaders().ToString().Trim());
                    properties.Add("TablePattern.Current.RowOrColumnMajor", pattern.Current.RowOrColumnMajor.ToString().Trim());
                }

                // hacked properties
                if (ae.Current.AutomationId.EndsWith("_AutomationHack"))
                {
                    ValuePattern pattern = ae.GetCurrentPattern(ValuePattern.Pattern) as ValuePattern;
                    foreach (ILEETHackModual hack in hacks)
                    {
                        pattern.SetValue("_____" + hack.HackFlag);
                        properties.Add(hack.PropertyName, pattern.Current.Value.ToString().Trim());
                    }
                }

                properties.Add(".Current.AutomationId", ae.Current.AutomationId);
                properties.Add(".Current.ClassName", ae.Current.ClassName);
                properties.Add(".Current.FrameworkId", ae.Current.FrameworkId);
                properties.Add(".Current.IsEnabled", ae.Current.IsEnabled.ToString().Trim());
                properties.Add(".Current.Name", ae.Current.Name);

                if(!cache.Keys.Contains(elem))
                    cache.Add(elem, properties);
            }
        }



        public AutomationElement GetAE(string elem)
        {
            return WidgetFinder.Find(elem, root);
        }
    }
}
